package se.webbzon.boltzmann.game.event;

import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import se.webbzon.boltzmann.game.sequence.Sequence;
import se.webbzon.boltzmann.projectile.Projectile3D;
import se.webbzon.boltzmann.timer.Timer;
import se.webbzon.boltzmann.timer.TimerListener;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldMovableObject;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.WorldStaticObject;
import se.webbzon.oschi01.worldobject.appearance.NoAppearance3D;

public class JumpToEvent extends AbstractTargetEvent {
	
	// The binding of this event
	private final WorldObject binding;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public JumpToEvent(Sequence sequence, WorldObject binding, String[] arguments) {
		super(sequence,arguments);
		this.binding = binding;
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override protected void onBegin(WorldArea world) {
		WorldObject target = getTarget();
		if (	target != null && 
				target instanceof WorldStaticObject && 
				binding instanceof WorldStaticObject) {
			WorldStaticObject j = (WorldStaticObject) binding;
			WorldStaticObject t = (WorldStaticObject) target;
			world.createInstance(new Jumper(j,t.getPosition()));
		} else
			end();
	}

	@Override protected void onEnd() {};
	
	/*============================================================
	Protected Methods
	============================================================*/
	
	/** Returns the binding of this event. **/
	protected WorldObject getBinding() {
		return binding;
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class Jumper extends WorldMovableObject {
		
		// The jumper and the target of this jumper instance
		private final WorldStaticObject jumper;
		private final Point3d target;
		
		// The timer associated with this jumper
		private final Timer timer;
		
		/*============================================================
		Constructors
		============================================================*/

		public Jumper(WorldStaticObject jumper, Point3d target) {
			super(WorldObject.onCreate + WorldObject.onStep, new NoAppearance3D());
			this.jumper = jumper;
			this.target = target;
			timer = new Timer(20);
			timer.addListener(new TimerListenerImpl(this));
		}
		
		/*============================================================
		Public Methods
		============================================================*/
		
		@Override public void onCreate(WorldArea world) {
			Point3d source = jumper.getPosition();
			setPosition(source.getX(), source.getY(), source.getZ());
			Vector3d v = Projectile3D.getVelocity(source, target, -0.5, 20);
			setVelocity(v.getX(), v.getY(), v.getZ());
			setAcceleration(0,-0.5,0);
			timer.start(world);
		}
		
		@Override public void onStep(WorldArea world) {
			jumper.setPosition(getX(), getY(), getZ());
		}
		
	}
	
	/** An implementation of a timer listener. **/
	private final class TimerListenerImpl implements TimerListener {
		
		private final Jumper jumper;
		
		public TimerListenerImpl(Jumper jumper) {
			this.jumper = jumper;
		}

		@Override public void onAlarm(Timer timer, WorldArea world) {
			double x = jumper.target.getX();
			double y = jumper.target.getY();
			double z = jumper.target.getZ();
			jumper.setVelocity(0, 0, 0);
			jumper.setAcceleration(0, 0, 0);
			jumper.setPosition(x, y, z);
			jumper.jumper.setPosition(x, y, z);
			world.destroyInstance(jumper);
			end();
		}
		
	}
	
}
